package com.zhl.model.log.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zhl.common.annotation.AutoLog;
import com.zhl.model.log.entity.SysLog;
import com.zhl.model.log.mapper.SysLogMapper;
import com.zhl.model.log.service.ISysLogService;
import com.zhl.model.log.vo.ExcelSysLog;
import com.zhl.model.log.vo.SysLogVo;
import com.zhl.model.sys.user.entity.User;
import com.zhl.util.*;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.Version;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;

/**
 * @Description: 系统日志信息
 * @date：   2019-12-27
 * @version： V1.0
 */
@Service
@Slf4j
public class SysLogServiceImpl extends ServiceImpl<SysLogMapper, SysLog> implements ISysLogService {

    @Autowired
    private SysLogMapper logMapper;


    @Override
    public IPage<SysLogVo> queryPageList(Page<SysLogVo> page, QueryWrapper queryWrapper) {
        return logMapper.queryPageList(page,queryWrapper);
    }


    /**
     * 获取操作日志信息,仅供excel导出使用
     * @param queryWrapper
     * @return
     */
    @Override
    public List<ExcelSysLog> querySysLogExcelList(QueryWrapper queryWrapper) {
        return logMapper.querySysLogExcelList(queryWrapper);
    }

    /**
     * 异步保存日志信息
     * @param joinPoint
     * @param time
     * @param sysLog
     */
    @Override
    @Async
    public void asyncSaveLog(ProceedingJoinPoint joinPoint,Long time,SysLog sysLog) {
        //获取登录用户信息
        User currentUser = UserUtil.getLoginUser();
        log.info("日志生成用户名：{}",currentUser.getUsername());
        currentUser.setUsername(MyAESUtil.Decrypt(currentUser.getUsername()));
        currentUser.setRealname(MyAESUtil.Decrypt(currentUser.getRealname()));
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        AutoLog syslog = method.getAnnotation(AutoLog.class);
        if(syslog != null){
            //注解上的描述,操作日志内容
            sysLog.setLogContent(syslog.value());
            sysLog.setLogType(syslog.logType());
            // 描述
            sysLog.setDescription(syslog.description());
            // 模块
            sysLog.setModuleName(syslog.moduleName());
            // 业务
            sysLog.setBusinessName(syslog.businessName());
        }
        //请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        sysLog.setMethod(className + "." + methodName + "()");
        //注解上的描述,操作日志内容
        if(1 == syslog.logType()){
            if("login".equals(syslog.value())){
                sysLog.setLogContent("用户名: "+currentUser.getUsername()+",登录成功！");
                sysLog.setOperateType("登录");
            }else if("logout".equals(syslog.value())){
                sysLog.setLogContent("用户名: "+currentUser.getUsername()+",退出成功！");
                sysLog.setOperateType("注销");
            }
        }else{
            sysLog.setLogContent(syslog.value());
            sysLog.setOperateType(syslog.value());
        }
        sysLog.setLogType(syslog.logType());//日志类型
        sysLog.setOperateOrgCode(currentUser.getOrgCode());//操作部门code
        //设置方法名
        sysLog.setMethod(className + "." + methodName + "()");
        //获取request
        HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
        //请求的参数
        sysLog.setRequestParam(getReqestParams(request,joinPoint));
        // 获取浏览器类型
        eu.bitwalker.useragentutils.UserAgent userAgent = eu.bitwalker.useragentutils.UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
        // 获取客户端浏览器
        Browser browser = userAgent.getBrowser();//浏览器客户端
        if(browser.equals(Browser.UNKNOWN) || browser == null){
            sysLog.setBrowser("未知浏览器");
        }else{
            String browserName = browser.getName();//浏览器名字
            String header = request.getHeader("User-Agent");
            if(StringUtils.isBlank(header)){
                sysLog.setBrowser(browserName);
            }else{
                Version version = browser.getVersion(header);
                if(version == null){
                    sysLog.setBrowser(browserName);
                }else{
                    String versionName = browser.getVersion(header).getVersion();//浏览器版本号
                    if(StringUtils.isBlank(versionName)){
                        sysLog.setBrowser(browserName);
                    }else{
                        sysLog.setBrowser(browserName+" "+versionName);
                    }
                }
            }

        }
        // 获取客户端操作系统
        String os = "";
        try {
            os = userAgent.getOperatingSystem().getName();
        }catch (Exception e){
            log.info("查询操作系统异常"+e.getMessage());
        }
        // 获取ip
        String IP = IPUtils.getIpAddr(request);
        // 获取地址
        String realAddressByIP = AddressUtils.getRealAddressByIP(IP);
        // 设置IP地址
        sysLog.setIp(IP);
        // 设置请求路径
        sysLog.setRequestUrl(request.getRequestURI());
        // 设置请求方法类型
        sysLog.setRequestType(request.getMethod());
        if("unknown".equalsIgnoreCase(os) || StringUtils.isBlank(os)){
            // 设置操作系统
            sysLog.setOs("其他");
        }else{
            // 设置操作系统
            sysLog.setOs(os);
        }

        // 设置地址
        sysLog.setLocation(realAddressByIP);
        if(currentUser != null){
            sysLog.setUsername(currentUser.getUsername());
            sysLog.setRealname(currentUser.getRealname());
        }else{
            log.info("*************用户信息不存在*************");
        }
        //耗时
        sysLog.setCostTime(time);
        //保存系统日志
        logMapper.insert(sysLog);
    }

    /**
     * 获取请求参数
     * @param request
     * @param joinPoint
     * @return
     */
    private String getReqestParams(HttpServletRequest request, JoinPoint joinPoint) {
        String httpMethod = request.getMethod();
        String params = "";
        if ("POST".equals(httpMethod) || "PUT".equals(httpMethod) || "PATCH".equals(httpMethod)) {
            Object[] paramsArray = joinPoint.getArgs();
            params = JSONObject.toJSONString(paramsArray);
        } else {
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            // 请求的方法参数值
            Object[] args = joinPoint.getArgs();
            // 请求的方法参数名称
            LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
            String[] paramNames = u.getParameterNames(method);
            if (args != null && paramNames != null) {
                for (int i = 0; i < args.length; i++) {
                    params += "  " + paramNames[i] + ": " + args[i];
                }
            }
        }
        return params;
    }
}
